﻿using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Furiant.Figment.Agents;
using Furiant.Figment.Agents.Inventory;

namespace Furiant.Figment.Items.Lootable
{
    public class EquipActionCriterionCollection<THasInventory> : IEnumerable<EquipActionCriterion<THasInventory>> where THasInventory:IHasInventory
    {
        #region Fields

        private readonly List<EquipActionCriterion<THasInventory>> _collection;

        #endregion

        #region Constructors

        public EquipActionCriterionCollection(IEnumerable<EquipActionCriterion<THasInventory>> collection)
        {
            _collection = collection.ToList();
        }

        #endregion

        #region Properties

        public IEnumerable<EquipActionCriterion<THasInventory>> Collection { get { return _collection; } }

        public EquipActionCriterion<THasInventory> this[int index] { get { return _collection[index]; } }

        #endregion

        #region Methods

        /// <summary>
        /// Returns whether the specified target satisfies all the requirements for the given EquipAction.
        /// </summary>
        /// <param name="target">The IHasInventory target to validate against.</param>
        /// <param name="action">The EquipAction to validate.</param>
        public bool AreAllSatisfied(THasInventory target, EquipAction action)
        {
            return _collection.All(p => p.Action == action && p.IsSatisfied(target));
        }

        /// <summary>
        /// Returns a collection of all requirements which are satisfied by the target for the given EquipAction.
        /// </summary>
        /// <param name="target">The IHasInventory target to validate against.</param>
        /// <param name="action">The EquipAction to validate.</param>
        /// <returns></returns>
        public IEnumerable<EquipActionCriterion<THasInventory>> GetSatisfied(THasInventory target, EquipAction action)
        {
            return _collection.Where(p => p.Action == action && p.IsSatisfied(target));
        }

        /// <summary>
        /// Returns a collection of all requirements which are not satisfied by the specified target for the given EquipAction.
        /// </summary>
        /// <param name="target">The IHasInventory target to validate against.</param>
        /// <param name="action">The EquipAction to validate.</param>
        public IEnumerable<EquipActionCriterion<THasInventory>> GetUnsatisfied(THasInventory target, EquipAction action)
        {
            return _collection.Where(p => p.Action == action && !p.IsSatisfied(target));
        }

        public IEnumerable<EquipActionCriterion<THasInventory>> GetUnsatisfied(THasInventory target, EquipAction action, out List<string> feedback)
        {
            var unsatisfied = GetUnsatisfied(target, action).ToList();
            feedback = unsatisfied.Select(u => u.Feedback).ToList();

            return unsatisfied;
        }

        #endregion

        #region Implementation of IEnumerable

        public IEnumerator<EquipActionCriterion<THasInventory>> GetEnumerator()
        {
            return _collection.GetEnumerator();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        #endregion
    }
}
